Zonnebatterij automaat


 


Deze schakeling is gebaseerd op de PIC 16C84 (of PIC 16F84) microcontroller. Deze chip is eigenlijk een kleine computer die in één enkele chip bevat is, inclusief RAM geheugen, EEPROM, I/O poorten, centrale verwerkingseenheid enz. Als je deze chip koopt, is hij uiteraard leeg en bevat geen enkel programma. Je moet de broncode (zie link onderaan) compileren en de resulterende machinecode naar de chip downloaden. Hierbij kun je gebruik maken van een kleine "programmer" die verbonden wordt tussen de parallelle poort van de PC en de chip. Voor meer in detail uitleg van dit soort dingen, kun je best eens naar volgende plaats surfen: Getting started with microcontrollers.


Een zonnebatterij automaat is bedoeld voor gebruik in de camper. De automaat vormt een "brug" tussen de twee batterijen (lichtbatterij en startbatterij). Deze brug kan aan of uit staan (de schakeling stuurt dit automatisch). Als de brug aan staat, staan de twee batterijen dus parallel.
De schakeling is uitsluitend bedoeld voor gebruik met een zonnepaneel met bijbehorende zonnelader. Dit zonnepaneel laadt normaal enkel de lichtbatterij op. Het idee achter deze schakeling is, wanneer de lichtbatterij bijna volledig is opgeladen, de "overtollige" zonne-energie te gebruiken om ook de startbatterij op te laden en op peil te houden. Op deze manier is het bijvoorbeeld mogelijk om de camper langere tijd niet te gebruiken en dan toch vlot de motor te kunnen starten, zelfs met een heleboel standby apparaten als radio, klokje enz. op de startbatterij.
Een andere functie van de automaat is om ook de startbatterij voor de leefruimte van de camper te gebruiken zodat er meer energie voorhanden is (dit kan uitsluitend indien de startbatterij ook geschikt is voor zowel starten als leefruimte, zgn. semi-tractie batterijen). De schakeling zorgt ervoor dat dit alleen kan als beide batterijen voldoende zijn opgeladen. De brug staat dan "aan" zodat beide batterijen tegelijk gebruikt worden om bijvoorbeeld tv te kijken. Als de spanning tot een bepaald niveau gezakt is wordt de brug uit gezet (en kijkt men dus verder tv op alleen de lichtbatterij), dit om te garanderen dat de startbatterij altijd voldoende energie heeft om de motor te kunnen starten.
De automaat is niet geschikt om de twee batterijen te koppelen tijdens rijden (vanwege de beperkte stroomsterkte van het gebruikte relais), gebruik hier dus een aparte klassieke relais of diode-brug voor. Wanneer het contact wordt ingeschakeld, schakelt de automaat de brug dan ook op "uit".


Het schema.

Verklaring van de werking:

De voeding voor de schakeling wordt betrokken uit de start batterij (via een 78L05 spanningsregelaar).

De spanning die gemeten wordt, is die van de lichtbatterij of van de combinatie licht/startbatterij (als de brug aan staat). De spanning wordt gemeten m.b.v. een spanningsdeler gevormd door R3/R4 om binnen 5V te blijven. De maximale ingangsspanning bedraagt 15V (voldoende voor de situatie waarbij de batterij maximaal is opgeladen en er volop zonlicht is).

Als de spanning onder 12,4 volt komt, wordt de brug uit gezet. Komt de spanning boven 13,5 volt, wordt de brug aan gezet. Tussen deze twee waarden wordt de brug gelaten zoals hij was (dat kan dus zowel aan als uit zijn, afhankelijk of men van de "hoge" kant komt dan wel de "lage").
De werking berust op het gebruik van 2 opamps die de spanning vergelijken met een vooraf ingestelde spanning. De ene opamp wordt gebruikt voor de "lage" drempel, de andere voor de "hoge" drempel. Het resultaat is telkens 0 of 1 (eronder of erover) en de twee uitgangen van de opamps worden naar de ingang van een microprocessor gestuurd die de sturing van de brug softwarematig afhandelt.
De twee opamps vinden we in IC LM324 dewelke er vier behuist, ruim voldoende dus.

De lage drempel en de hoge drempel kunnen best op ca. 12,4 resp. 13,5 volt staan, instellen kan via resp. POT1 en POT2.

De brug zelf bestaat uit een zgn. bistabiele relais die twee spoelen heeft (een voor uit en een voor aan). Dit relais heeft een spoelspanning van 12V en een schakelstroomsterkte van 12A bij 12V.
Het contact gedeelte van de brug is in het schema niet getoond, je moet gewoon het maak-contact van het relais gebruiken en een uiteinde met de startbatterij verbinden, het andere met de lichtbatterij.
Een bistabiele relais gebruikt geen stroom in welke toestand hij ook staat (brug aan of brug uit). Enkel tijdens het omschakelen is korte tijd een stroom nodig (pulsje van ca. 0,2 seconden).
De beide spoelen van het bistabiel relais worden gestuurd met een BC337 transistor, deze is hiervoor sterk genoeg. Merk op dat de spoelen via het 12V circuit gestuurd worden en niet via het 5V circuit.
Relay 3 in de schakeling stelt eigenlijk de "uit" spoel voor, Relay 2 de "aan" spoel. Relay 1, niet strikt noodzakelijk, dient eigenlijk om tijdens het omschakelen van de brug een eventueel extern alarsysteem even te deactiveren. Dit komt uitsluitend omdat ik een alarmsysteem heb dat reageert op plotselinge veranderingen van de spanning en het omschakelen van de brug zou het alarm laten afgaan. Je kan Relay 1 dus rustig weglaten als je een dergelijke interface met je alarmsysteem niet nodig hebt.

Men kan ten allen tijde met een drukknop de brug manueel bedienen met behulp van SW1 (maar alleen indien de spanning in het zweef-bereik zit t.t.z. tussen ca. 12,4 en 13,5 Volt).

Het relais is dus zoals gezegd een bistabiel relais van een zo fors mogelijke uitvoering, bijvoorbeeld Conrad bestelnr. 504173 - 62. Deze schakelt tot 16A. De software zorgt voor de aansturing. Indien men een bistabiel relais zou kunnen vinden van een nog hogere contact)amperage (vb. 30A) wat mij dus niet gelukt is, zou men de schakeling ook kunnen gebruiken om een brug te leggen tijdens het rijden. Een software aanpassing is dan wel noodzakelijk.

Handig is ook om twee LEDs (met voorschakelweerstand) parallel op de spoelen van het relais te zetten (niet getekend in het schema) zodat men kan zien wanneer omgeschakeld wordt (kortstondig aangaan van de LED).


Hieronder het blokschema voor aansluiting van de zonnebatterij automaat in verhouding tot de bestaande bedrading in de camper.
De rode lijnen geven de nieuw te maken bedrading weer.


Aansluitschema in verhouding tot de rest van de camper.


Source code:

;;



;; 
;;    Zonnebatterij automaat, a PIC 16F84 program to switch two lead-acid batteries in parallel
;;    when there is enough sunlight.
;;    
;;    Copyright (C) 2000  Geert Van Espen (geert@vanespen.com)
;;
;;
        LIST P=16F84

        errorlevel 0,-305

        
        processor 16f84
        include "p16f84.inc"

 __CONFIG _CP_OFF & _RC_OSC & _PWRTE_ON  & _WDT_ON


;
;
;
;
;     commando om dit project naar de pic te sturen:
;       TOPIC -RWG SOLARSW.HEX
;
;
;
;
;
;      current settings: low level  = 12.29 V
;                        high level = 13.45 V
;




                                ; general purpose register allocation


werk    equ     0x0c            ; werkregister
t1      equ     0x0d            ; telwerk 1
t2      equ     0x0e            ; telwerk 2
        
TIJDl   equ     0x10            ; to keep track of time
TIJDh   equ     0x11

ddd     equ     0x13            ; debug only

KLAPPERTIJD0 equ 0x14           ; hysteresis 0
KLAPPERTIJD1 equ 0x15           ; hysteresis 1
KLAPPERTIJD2 equ 0x16           ; hysteresis 2
KLAPPERTIJD3 equ 0x17           ; hysteresis 3

RB0_STAND equ   0x18            ; 0=uit 1=aan
RB1_STAND equ   0x19            ; 0=uit 1=aan
RB2_STAND equ   0x1a            ; 0=uit 1=aan
RB3_STAND equ   0x1b            ; 0=uit 1=aan

tempvar equ     0x1c            ;

Wl      equ     0x20            ;
Wh      equ     0x21            ;
BRUG    equ     0x22            ; 0 = geen doorkoppeling batterijen
                                ; 1 = wel doorkoppeling batterijen
CONTACT equ     0x23            ; 0 = contactsleutel uit
                                ; 1 = contactsleutel aan
PrevRB0 equ     0x24            ; vorige RB0 situatie
PrevRB1 equ     0x25            ; vorige RB1 situatie
PrevRB2 equ     0x26            ; vorige contact situatie
PrevBtn equ     0x27            ; vorige pushbutton situatie

; tijdconstanten
;;;;;;;;;;;;;;;;

m_input_a equ   b'00000000'     ; input mask, which bits are input
m_input_b equ   b'11111111'     ;

        org     0x00            ; reset vector
        goto    main

        dt      "2000-10-10 geert@vanespen.com Zonnebatterij automaat"






;***********************************************************************
;*                                                                     *
;*     initialise                                                      *
;*                                                                     *
;***********************************************************************

initialise:                     ; set up ports

        MOVLW    0              ;
        TRIS     5              ;
        MOVLW    0x0F           ;
        TRIS     6              ;
        MOVLW    0x80           ;
        OPTION                  ;


        clrf    TIJDl           ; initialisaties
        clrf    TIJDh           ;
        clrf    KLAPPERTIJD0    ;
        clrf    KLAPPERTIJD1    ;
        clrf    KLAPPERTIJD2    ;
        clrf    KLAPPERTIJD3    ;
        clrf    RB0_STAND       ;
        clrf    RB1_STAND       ;
        clrf    RB2_STAND       ;
        clrf    RB3_STAND       ;
        clrf    BRUG            ;
        clrf    CONTACT         ;
        clrf    PrevRB0         ;
        clrf    PrevRB1         ;
        clrf    PrevRB2         ;
        clrf    PrevBtn         ;

        clrf    PORTA           ; UIT laag
        clrf    PORTB


; uitgang even aan en uit laten knipperen om te laten zien dat het
; apparaat werkt
        movlw   0xFE            ; startwaarde
        movwf   PORTA           ;

        movlw   6               ; knipper 3 keer
        movwf   t1              ;
functiontest:
        movlw   0x19            ; wacht halve seconde
        call    wachtlus        ;
        movlw   0xFF            ;
        xorwf   PORTA, f        ;
        decfsz  t1, f           ;
        goto    functiontest    ;
        
        clrf    PORTA           ; UIT laag

        retlw   0


;***********************************************************************
;*                                                                     *
;*     wachtlus                                                        *
;*                                                                     *
;***********************************************************************
wachtlus:
; wacht x keer 18 milliseconden, met x in w

        movwf   werk            ; zet w in werk
; debug only
; movlw 1
; movwf werk

slapertje:
        sleep                   ;
        decfsz  werk, f         ;
        goto    slapertje       ;
        retlw   0               ;




;***********************************************************************
;*                                                                     *
;*     test_portRB0                                                    *
;*                                                                     *
;***********************************************************************
; hysteresis voor poort RB0: als RB0 een tijdje 0 is wordt RB0_STAND
; ook 0; als RB0 1 is wordt RB0_STAND onmiddellijk 1
test_portRB0:
        movf    PORTB, w        ; w = PORTB
        andlw   1               ; we willen alleen RB0
        movwf   tempvar         ;
        movf    tempvar, w      ;
        btfss   tempvar, 0      ;
        goto    test0_low       ;
        movlw   1               ;
        movwf   RB0_STAND       ;
        clrf    KLAPPERTIJD0    ; KLAPPERTIJD0 = 0
        retlw   0               ;
test0_low:
        subwf   RB0_STAND, w    ;
        btfss   STATUS, Z       ; RB0 input = RB0_STAND?
        goto    test0_hyst1     ;
        clrf    KLAPPERTIJD0    ; ja: KLAPPERTIJD0 = 0
        goto    test0_hyst2     ;
test0_hyst1:
        incf    KLAPPERTIJD0, f ; neen: verhoog KLAPPERTIJD0
test0_hyst2:
        btfss   KLAPPERTIJD0, 2 ; KLAPPERTIJD0 hoog?
        goto    test0_hyst3     ; neen: gedaan
        movf    tempvar, w      ;
        movwf   RB0_STAND       ; ja: RB0_STAND = RB0 input
        clrf    KLAPPERTIJD0    ; KLAPPERTIJD0 = 0
test0_hyst3:

        retlw   0               ;




;***********************************************************************
;*                                                                     *
;*     test_portRB1                                                    *
;*                                                                     *
;***********************************************************************
; hysteresis voor poort RB1: als RB1 een tijdje 0 is wordt RB1_STAND
; ook 0; als RB1 1 is wordt RB1_STAND onmiddellijk 1
test_portRB1:
        movf    PORTB, w        ; w = PORTB
        andlw   2               ; we willen alleen RB1
        movwf   tempvar         ;
        bcf     STATUS, C       ;
        rrf     tempvar, f      ;
        movf    tempvar, w      ;
        btfss   tempvar, 0      ;
        goto    test1_low       ;
        movlw   1               ;
        movwf   RB1_STAND       ;
        clrf    KLAPPERTIJD1    ; KLAPPERTIJD1 = 0
        retlw   0               ;
test1_low:
        subwf   RB1_STAND, w    ;
        btfss   STATUS, Z       ; RB1 input = RB1_STAND?
        goto    test1_hyst1     ;
        clrf    KLAPPERTIJD1    ; ja: KLAPPERTIJD1 = 0
        goto    test1_hyst2     ;
test1_hyst1:
        incf    KLAPPERTIJD1, f ; neen: verhoog KLAPPERTIJD1
test1_hyst2:
        btfss   KLAPPERTIJD1, 2 ; KLAPPERTIJD1 hoog?
        goto    test1_hyst3     ; neen: gedaan
        movf    tempvar, w      ;
        movwf   RB1_STAND       ; ja: RB1_STAND = RB1 input
        clrf    KLAPPERTIJD1    ; KLAPPERTIJD1 = 0
test1_hyst3:

        retlw   0               ;




;***********************************************************************
;*                                                                     *
;*     test_portRB2                                                    *
;*                                                                     *
;***********************************************************************
; hysteresis voor poort RB2: als RB2 een tijdje 1 is wordt RB2_STAND
; ook 1; als RB2 een tijdje nul is wordt RB2_STAND ook nul
test_portRB2:
        movf    PORTB, w        ; w = PORTB
        andlw   0x04            ; we willen alleen RB2
        movwf   tempvar         ;
        bcf     STATUS, C       ;
        rrf     tempvar, f      ;
        rrf     tempvar, f      ;
        movf    tempvar, w      ;
        subwf   RB2_STAND, w    ;
        btfss   STATUS, Z       ; RB2 input = RB2_STAND?
        goto    test2_hyst1     ;
        clrf    KLAPPERTIJD2    ; ja: KLAPPERTIJD2 = 0
        goto    test2_hyst2     ;
test2_hyst1:
        incf    KLAPPERTIJD2, f ; neen: verhoog KLAPPERTIJD2
test2_hyst2:
        btfss   KLAPPERTIJD2, 1 ; KLAPPERTIJD2 hoog?
        goto    test2_hyst3     ; neen: gedaan
        movf    tempvar, w      ;
        movwf   RB2_STAND       ; ja: RB2_STAND = RB2 input
        clrf    KLAPPERTIJD2    ; KLAPPERTIJD2 = 0
test2_hyst3:

        retlw   0               ;


;***********************************************************************
;*                                                                     *
;*     test_portRB3                                                    *
;*                                                                     *
;***********************************************************************
; hysteresis voor poort RB3: als RB3 een tijdje 1 is wordt RB3_STAND
; ook 1; als RB3 een tijdje nul is wordt RB3_STAND ook nul
test_portRB3:
        movf    PORTB, w        ; w = PORTB
        andlw   0x08            ; we willen alleen RB3
        movwf   tempvar         ;
        bcf     STATUS, C       ;
        rrf     tempvar, f      ;
        rrf     tempvar, f      ;
        rrf     tempvar, f      ;
        movf    tempvar, w      ;
        subwf   RB3_STAND, w    ;
        btfss   STATUS, Z       ; RB3 input = RB3_STAND?
        goto    test3_hyst1     ;
        clrf    KLAPPERTIJD3    ; ja: KLAPPERTIJD3 = 0
        goto    test3_hyst2     ;
test3_hyst1:
        incf    KLAPPERTIJD3, f ; neen: verhoog KLAPPERTIJD3
test3_hyst2:
        btfss   KLAPPERTIJD3, 2 ; KLAPPERTIJD3 hoog?
        goto    test3_hyst3     ; neen: gedaan
        movf    tempvar, w      ;
        movwf   RB3_STAND       ; ja: RB3_STAND = RB3 input
        clrf    KLAPPERTIJD3    ; KLAPPERTIJD3 = 0
test3_hyst3:

        retlw   0               ;



;***********************************************************************




;***********************************************************************
;*                                                                     *
;*     programma                                                       *
;*                                                                     *
;***********************************************************************



main:
        btfsc   STATUS, NOT_TO  ; if this is a reset or power-up ...
        call    initialise      ; set port drivers and WDT prescaler





        movlw   1               ; veronderstel contact aan
        movwf   CONTACT         ;

        movlw   3               ;
        movwf   PrevRB0         ;
        movwf   PrevRB1         ;
        movwf   PrevRB2         ;
        movwf   PrevBtn         ;

start:

main_loop:

;
; LAGE DREMPELSPANNING (poort RB0)
;
        call    test_portRB0    ; test spanning op poort RB0
        movf    PrevRB0, w      ; test of RB0_STAND veranderd is
        subwf   RB0_STAND, w    ;
;;;;;   btfsc   STATUS, Z       ; is de stand veranderd?
;;;;;   goto    test0_af        ;
; veranderd
        movf    RB0_STAND, w    ; ja, de stand is veranderd
        movwf   PrevRB0         ;

        btfsc   RB0_STAND, 0    ; is spanning laag?
        goto    test0_af        ; neen, gedaan
        btfss   BRUG, 0         ; ja: test of brug al af stond
        goto    test0_af        ; brug af: gedaan
        bsf     PORTA, 2        ; spanning laag: alarm-disable relais
        bsf     PORTA, 0        ;   en RA0 een tijdje aanzetten

        movlw   0xc             ; wacht fractie seconde
        call    wachtlus        ;

        clrf    BRUG            ; bewaar huidige toestand

        bcf     PORTA, 0        ; poorten terug uitzetten
        bcf     PORTA, 2        ;

        movlw   0x6f            ; wacht 2 seconden
        call    wachtlus        ;
test0_af:


;
; HOGE DREMPELSPANNING (poort RB1)
;
        btfsc   CONTACT, 0      ; als contact aan,
        goto    test1_af        ; dan nooit brug maken!

        call    test_portRB1    ; test spanning op poort RB1
        movf    PrevRB1, w      ;
        subwf   RB1_STAND, w    ;
;;;;;   btfsc   STATUS, Z       ; is de stand veranderd?
;;;;;   goto    test1_af        ;
; veranderd
        movf    RB1_STAND, w    ; ja, de stand is veranderd
        movwf   PrevRB1         ;

        btfss   RB1_STAND, 0    ; is spanning hoog?
        goto    test1_af        ; neen, gedaan
        btfsc   BRUG, 0         ; ja: test of brug al aan stond
        goto    test1_af        ; brug aan: gedaan
        bsf     PORTA, 2        ; spanning hoog: alarm-disable relais
        bsf     PORTA, 1        ;   en RA1 een tijdje aanzetten

        movlw   0xc             ; wacht fractie seconde
        call    wachtlus        ;

        bsf     BRUG, 0         ; bewaar huidige toestand

        bcf     PORTA, 1        ; poorten terug uitzetten
        bcf     PORTA, 2        ;

        movlw   0x6f            ; wacht 2 seconden
        call    wachtlus        ;
test1_af:


;
; CONTACTSLEUTEL (poort RB2)
;

ContactSleutel:

        call    test_portRB2    ; test spanning op poort RB2
        movf    PrevRB2, w      ;
        subwf   RB2_STAND, w    ;
        btfsc   STATUS, Z       ; is de stand veranderd?
        goto    test2_af        ;
; veranderd
        movf    RB2_STAND, w    ; ja, de stand is veranderd
        movwf   PrevRB2         ;

        btfsc   RB2_STAND, 0    ; is contact aan?
        goto    test2_aan       ;
        clrf    CONTACT         ; neen: bewaar huidige toestand
        bsf     PrevRB0, 3      ; herinitialiseer spanningstesten
        bsf     PrevRB1, 3      ;
        goto    test2_af        ;
test2_aan:
        bsf     CONTACT, 0      ; bewaar huidige toestand

        bsf     PORTA, 2        ; alarm-disable relais en
        bsf     PORTA, 0        ;   RA0 een tijdje aanzetten

        movlw   0xc             ; wacht fractie seconde
        call    wachtlus        ;

        clrf    BRUG            ; bewaar huidige toestand

        bcf     PORTA, 0        ; poorten terug uitzetten
        bcf     PORTA, 2        ;

        movlw   0xfe            ; wacht 5 seconden
        call    wachtlus        ;


test2_af:


;
; PUSHBUTTON (poort RB3)
;
        btfss   CONTACT, 0      ; als contact aan,
        goto    PushButton      ; dan nooit brug maken!
        clrf    PrevBtn         ;
        goto    PushButton_samen;

PushButton:
        call    test_portRB3    ; als pushbutton gedrukt is,
        movf    PrevBtn, w      ;   dan toggelen
        subwf   RB3_STAND, w    ;
        btfsc   STATUS, Z       ; is de stand veranderd?
        goto    PushButton_gelijk;
PushButton_changed:
        movf    RB3_STAND, w    ; ja: PrevBtn = RB3_STAND
        movwf   PrevBtn         ;

        btfss   RB3_STAND, 0    ; is pushbutton gedrukt?
        goto    PushButton_af   ;
        movlw   1               ; ja: toggle BRUG
        xorwf   BRUG, f         ;

; reflect BRUG value onto output ports
        btfss   BRUG, 0         ; BRUG waarde testen
        goto    PushButton_Reflect_uit;
PushButton_Reflect_aan:
        bsf     PORTA, 2        ; alarm-disable relais en
        bsf     PORTA, 1        ;   RA1 een tijdje aanzetten
        movlw   0xc             ; wacht fractie seconde
        call    wachtlus        ;
        bcf     PORTA, 1        ; poorten terug uitzetten
        bcf     PORTA, 2        ;
        goto    PushButton_samen;
PushButton_Reflect_uit:
        bsf     PORTA, 2        ; alarm-disable relais en
        bsf     PORTA, 0        ;   RA0 een tijdje aanzetten
        movlw   0xc             ; wacht fractie seconde
        call    wachtlus        ;
        bcf     PORTA, 0        ; poorten terug uitzetten
        bcf     PORTA, 2        ;
        goto    PushButton_samen;
PushButton_samen:


PushButton_gelijk:
        goto    PushButton_af   ;


PushButton_af:





        movlw   0x2             ; wacht fractie seconde
        call    wachtlus        ;

        goto    start           ;

        ;; 
        ;;
        
        end





Download bron code (assembler)       Download hex bestand (machine code)



Het afgewerkte apparaat.

  Home         Terug naar Electronica projecten